package com.lazi.june.web.interceptor;

import com.lazi.june.common.annotation.UnLogin;
import com.lazi.june.common.base.ActiveUser;
import com.lazi.june.common.base.ActiveUserHolder;
import com.lazi.june.common.base.RequestConst;
import com.lazi.june.common.base.Result;
import com.lazi.june.common.exception.ExceptionEnum;
import com.lazi.june.common.util.JsonUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.lang.NonNull;
import org.springframework.util.CollectionUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.Optional;

/**
 * desc: 认证过滤器
 *
 * @author huliqian
 * @since 2025/8/21
 */
@Slf4j
@RequiredArgsConstructor
public class AuthInterceptor implements HandlerInterceptor {

    private final Map<String, HeaderCheckStrategy> headerCheckStrategyMap;


    @Override
    public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) throws Exception {

        String method = request.getMethod();
        if (HttpMethod.OPTIONS.matches(method)) {
            return false;
        }
        if (!(handler instanceof HandlerMethod handlerMethod)) {
            return true;
        }
        if (this.noTokenHandler(handlerMethod.getMethod())) {
            return true;
        }

        String userInfo = request.getHeader(RequestConst.USER_INFO);
        try {
            ActiveUser activeUser = Optional.ofNullable(userInfo)
                    .map(i -> JsonUtil.toBean(i, ActiveUser.class))
                    .orElseThrow(() -> Result.failed(ExceptionEnum.ERROR_USER_DEFECT_TOKEN));
            this.checkHeader();
            //从请求头中获取用户信息
            ActiveUserHolder.set(activeUser);
            return true;
        } catch (Exception e) {
            ActiveUserHolder.remove();
            log.error("认证失败:{}", e.getMessage());
            return false;
        }
    }

    /**
     * 验证请求头
     */
    public void checkHeader() {
        if (CollectionUtils.isEmpty(headerCheckStrategyMap)) {
            return;
        }
        headerCheckStrategyMap.values().forEach(HeaderCheckStrategy::check);
    }


    /**
     * 不需要token
     *
     * @param ownMethod Method
     * @return boolean
     */
    private boolean noTokenHandler(Method ownMethod) {
        return Optional.ofNullable(ownMethod.getAnnotation(UnLogin.class))
                .or(() -> Optional.ofNullable(ownMethod.getDeclaringClass().getAnnotation(UnLogin.class)))
                .isPresent();
    }


    @Override
    public void afterCompletion(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler, Exception ex) throws Exception {
        ActiveUserHolder.remove();
        HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    }
}
